package switchviz.graphic.gauge.bargraph.scale;

import java.text.DecimalFormat;

import javax.media.opengl.GL;

import org.jdom.Element;

import switchviz.graphic.GraphicUtils;
import switchviz.graphic.IGraphicsPanel;
import switchviz.graphic.gauge.IScale;
import switchviz.graphic.gauge.bargraph.BarGraphPanel;

public class BarGraphScale extends IScale
{
	private BarGraphScaleDataModel _datamodel = null;
	private Element _root = null;
	private BarGraphScalePanel _panel = null;
	private BarGraphScalePersistence _nodehandler = null;
	private float _datamin = 0.0f;
	private float _datamax = 100.0f;
	private float _datadepth = 1.0f;
	private int _representation = BarGraphPanel.REP_LINEAR;
	private int _list = 0;
	private boolean _enable = true;
	
	public BarGraphScaleDataModel getScaleModel()
	{
		if(_datamodel == null)
			_datamodel = getNodeHandler().getDataModelFromElement();
		return _datamodel;
	}
	
	public BarGraphScale(Element root, float datamax, float datamin, float datadepth, int representation, boolean enable)
	{
		_root = root;
		_datamin = datamin;
		_datamax = datamax;
		_datadepth = datadepth;
		_representation = representation;
		_enable = enable;
	}
	
	public void initialize(GL gl)
	{
		_list = gl.glGenLists(1);
		gl.glNewList(_list, GL.GL_COMPILE);
		if (_representation == BarGraphPanel.REP_LINEAR)
			drawLinearScale(gl);
		else
			drawLogScale(gl);
		gl.glEndList();
	}
	
	public void draw(GL gl)
	{
		gl.glCallList(_list);
	}
	
	public void drawLogScale(GL gl)
	{
		gl.glBegin(GL.GL_LINES);
		gl.glColor4f(getScaleModel().getCoordinatecolor()[0], getScaleModel().getCoordinatecolor()[1], getScaleModel().getCoordinatecolor()[2], 1.0f);
		gl.glPointSize(2.0f);
		gl.glVertex3f(0.0f, 0.0f, 0.0f);
		gl.glVertex3f(0.0f, 0.0f, -1.0f * _datadepth);
		gl.glVertex3f(0.0f, 0.0f, 0.0f);
		gl.glVertex3f(0.0f, 1.0f, 0.0f);
		gl.glVertex3f(0.0f, 0.0f, 0.0f);
		gl.glVertex3f(1.0f, 0.0f, 0.0f);
		gl.glEnd();
		
		double label = _datamin;
		double labelstep = 1;
		float intervall = 1.0f / ( getScaleModel().getNumgridlines());
		label = Math.max(_datamin, Float.MIN_VALUE);
		labelstep = Math.pow(10, (Math.log10(_datamax)-Math.log10(_datamin))/(getScaleModel().getNumgridlines()));
		
		DecimalFormat df = new DecimalFormat();
		df.setMaximumFractionDigits(2);
		df.setMinimumFractionDigits(2);
		for(int i = 0; i < getScaleModel().getNumgridlines() + 1; ++i)
		{
			// draw time grid and gridvalues
			gl.glColor4f(getScaleModel().getGridcolor()[0], getScaleModel().getGridcolor()[1], getScaleModel().getGridcolor()[2], 1.0f);
			gl.glBegin(GL.GL_LINES);
			gl.glVertex3f(0.0f, i * intervall, 0.0f);
			gl.glVertex3f(0.0f, i * intervall, -1.0f * _datadepth);
			gl.glEnd();
			
			gl.glPushMatrix();
			gl.glTranslatef(0.0f, i * intervall, 0.1f);
			gl.glRotatef(90, 0.0f, 1.0f, 0.0f);
			GraphicUtils.drawString(gl, 4, GraphicUtils.ALIGN_RIGHT, GraphicUtils.FONT_ROMAN, label);
			gl.glPopMatrix();
			
			// draw amplitude ticks and tickvalues
			gl.glBegin(GL.GL_LINES);
			gl.glVertex3f(0.0f, i * intervall, 0.0f);
			gl.glVertex3f(1.0f, i * intervall, 0.0f);
			gl.glEnd();
			
			gl.glPushMatrix();
			gl.glTranslatef(-0.1f, i * intervall, 0.0f);
			GraphicUtils.drawString(gl, 4, GraphicUtils.ALIGN_RIGHT, GraphicUtils.FONT_ROMAN, label);
			gl.glPopMatrix();
			label *= labelstep;
		}
	}
	
	public void drawLinearScale(GL gl) 
	{
		gl.glBegin(GL.GL_LINES);
		
		if (_enable)
			gl.glColor4f(getScaleModel().getCoordinatecolor()[0], getScaleModel().getCoordinatecolor()[1], getScaleModel().getCoordinatecolor()[2], 1.0f);
		else
			gl.glColor4f(getScaleModel().getCoordinatecolor()[0], getScaleModel().getCoordinatecolor()[1], getScaleModel().getCoordinatecolor()[2], 0.3f);
		
		gl.glPointSize(2.0f);
		gl.glVertex3f(0.0f, 0.0f, 0.0f);
		gl.glVertex3f(0.0f, 0.0f, -1.0f * _datadepth);
		gl.glVertex3f(0.0f, 0.0f, 0.0f);
		gl.glVertex3f(0.0f, 1.0f, 0.0f);
		gl.glVertex3f(0.0f, 0.0f, 0.0f);
		gl.glVertex3f(1.0f, 0.0f, 0.0f);
		gl.glEnd();
		
		float intervall = 1.0f / getScaleModel().getNumgridlines();
		float unit = (_datamax - _datamin) / getScaleModel().getNumgridlines();
		
		if(_enable)
			gl.glColor4f(getScaleModel().getGridcolor()[0], getScaleModel().getGridcolor()[1], getScaleModel().getGridcolor()[2], 1.0f);
		else
			gl.glColor4f(getScaleModel().getGridcolor()[0], getScaleModel().getGridcolor()[1], getScaleModel().getGridcolor()[2], 0.3f);
		
		for(int i = 0; i <= getScaleModel().getNumgridlines(); ++i)
		{
			// draw time grid and gridvalues
			
			
			gl.glBegin(GL.GL_LINES);
			gl.glVertex3f(0.0f, i * intervall, 0.0f);
			gl.glVertex3f(0.0f, i * intervall, -1.0f * _datadepth);
			gl.glEnd();
			
			gl.glPushMatrix();
			gl.glTranslatef(0.0f, i * intervall, 0.1f);
			gl.glRotatef(90, 0.0f, 1.0f, 0.0f);
			GraphicUtils.drawString(gl, 4, GraphicUtils.ALIGN_RIGHT, GraphicUtils.FONT_ROMAN, "" + (unit * i + _datamin));
			gl.glPopMatrix();
			
			// draw amplitude ticks and tickvalues
			gl.glBegin(GL.GL_LINES);
			gl.glVertex3f(0.0f, i * intervall, 0.0f);
			gl.glVertex3f(1.0f, i * intervall, 0.0f);
			gl.glEnd();
			
			gl.glPushMatrix();
			gl.glTranslatef(-0.1f, i * intervall, 0.0f);
			GraphicUtils.drawString(gl, 4, GraphicUtils.ALIGN_RIGHT, GraphicUtils.FONT_ROMAN, "" + (unit * i + _datamin));
			gl.glPopMatrix();
		}
		
		
	}

	public Element getElement() 
	{
		return getSetupPanel().getElement();
	}

	public IGraphicsPanel getSetupPanel() 
	{
		if(_panel == null)
			_panel = new BarGraphScalePanel(_root);
		return _panel;
	}
	
	private BarGraphScalePersistence getNodeHandler()
	{
		if(_nodehandler == null)
			_nodehandler = new BarGraphScalePersistence(_root);
		return _nodehandler;
	}

	@Override
	public void setElement(Element node) 
	{
		_root = node;
		_nodehandler = null;
		_datamodel = null;
		_panel = null;
	}
	

}
